//========================================================= 
/**@file Runnable
 * @brief 
 * 
 * @date 25-07-17   14:55:28
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_RUNABLE_H_
#define _LIBZHOUYB_RUNABLE_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"

#include <vector>
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace tools {
//--------------------------------------------------------- 
/// 运行接口
struct IRunnableBehavior
{
    /// 是否结束
    virtual bool IsDone() const = 0;
    /// 每个渲染周期执行
    virtual bool Update(Timer::TickType tick) = 0;
    /// 固定频率执行
    virtual bool FixedUpdate(Timer::TickType tick, uint delta) = 0;
};
//--------------------------------------------------------- 
/// 执行器
struct IRunnable
{
    /// 持续执行一段时间
    virtual uint Run(IRunnableBehavior& r, uint duration = 0) = 0;
};
//--------------------------------------------------------- 
/// 适配多个IRunnableBehavior
class MultipleRunnable : public IRunnableBehavior
{
protected:
    std::vector<IRunnableBehavior*> _queue;
public:
    void Append(IRunnableBehavior& r)
    {
        _queue.push_back(&r);
    }
    void Remove()
    {
        _queue.clear();
    }

    bool IsDone() const
    {
        bool is_done = false;
        for (size_t i = 0; i < _queue.size(); ++i)
        {
            is_done |= _queue[i]->IsDone();
        }
        return is_done;
    }
    bool Update(Timer::TickType tick)
    {
        bool is_busy = false;
        for (size_t i = 0; i < _queue.size(); ++i)
        {
            is_busy |= _queue[i]->Update(tick);
        }
        return is_busy;
    }
    bool FixedUpdate(Timer::TickType tick, uint delta)
    {
        bool is_busy = false;
        for (size_t i = 0; i < _queue.size(); ++i)
        {
            is_busy |= _queue[i]->FixedUpdate(tick, delta);
        }
        return is_busy;
    }
};
//--------------------------------------------------------- 
/// 执行器
class RunnableController : public IRunnable, public InterruptBehavior
{
public:
    //----------------------------------------------------- 
    /// 固定帧间隔
    uint FixedUpdateIntervalMs;
    /// 空闲Update的最大次数
    uint UpdateMaxIdleCount;
    /// 是否允许Update间进行休眠
    bool IsAllowUpdateSleep;
    //----------------------------------------------------- 
public:
    //----------------------------------------------------- 
    RunnableController() : FixedUpdateIntervalMs(33), UpdateMaxIdleCount(100), IsAllowUpdateSleep(false) {}
    //----------------------------------------------------- 
    virtual uint Run(IRunnableBehavior& r, uint duration = 0)
    {
        const uint MIN_WAIT_TIME_MS = 10;

        Timer::TickType last_tick = Timer::TimeTick();
        Timer::TickType fixed_start_tick = last_tick;
        uint fixed_count = 0;
        Timer::TickType exit_tick = last_tick + duration;
        while (!r.IsDone())
        {
            Timer::TickType tick = Timer::TimeTick();
            for (uint i = 0; i < UpdateMaxIdleCount; ++i)
            {
                if (r.Update(tick))
                    break;
            }
            uint delta = tick - last_tick;
            if (delta < FixedUpdateIntervalMs)
            {
                // 休眠的最小粒度
                if (IsAllowUpdateSleep && ((FixedUpdateIntervalMs - delta) > MIN_WAIT_TIME_MS))
                {
                    Timer::Wait(MIN_WAIT_TIME_MS);
                }
                continue;
            }
            r.FixedUpdate(tick, delta);
            ++fixed_count;
            last_tick = tick;

            if (duration && exit_tick < tick)
                break;

            if (InterruptBehavior::Implement(*this))
                break;
        }
        if (fixed_count > 0)
        {
            uint fps = (Timer::TimeTick() - fixed_start_tick) / fixed_count;
            return fps;
        }
        return 0;
    }
    //----------------------------------------------------- 
};
//--------------------------------------------------------- 
} // namespace tools
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
 //--------------------------------------------------------- 
 #endif // #ifndef _LIBZHOUYB_RUNABLE_H_
//========================================================= 